/**
 * 复数对象类
 * 如果复数虚部是0，数学意义数值是实数，但该实例对象仍然是一个Complex对象类型，而非Number类型
 * @param real 复数的实部，必须
 * @param imaginary 复数的虚部，必须
 * @param suffix  复数的后缀，i或j，必须。
 */
class Complex{
    constructor(real , imaginary, suffix){
        //确保两个实参都是数字
        if( !isNumber(real) || !isNumber(imaginary)){
            throw new TypeError('All parameters must be numeric');        //如果不都是数字则抛出错误
        }
        //检查后缀
        if(!(suffix === 'i' || suffix === 'j')){
            throw new TypeError('The complex suffix must be i or j');        //如果不是i或者j则抛出错误
        }
        this.r = real
        this.i = imaginary
        this.s = suffix || 'i'
    }
    /**
     * 将复数对象装换为一个字符串
     * @returns {string}
     */
    toString(){
        if(this.r ===0) {
            if (this.i === 0) {
                return '0'
            }
            if (this.i === 1) {
                return this.s
            }
            if (this.i > 1) {
                return this.i+this.s
            }
            if (this.i === -1) {
                return '-'+this.s
            }
            if (this.i < -1) {
                return this.i+this.s
            }

        } else{
            if( this.i === 0){
                return this.r
            }
            if( this.i === 1){
                return this.r+'+'+this.s
            }
            if( this.i === -1){
                this.i = '-'
                return this.r+'-'+this.s
            }
            if( this.i > 1){
                return this.r+'+'+this.i+this.s
            }
            if(this.i < -1){
                return this.r+''+this.i+this.s
            }
        }
    }
}

/**
 * 复数的操作对象：
 * 公有方法：
 * set:创建一个复数，返回值是一个Complex实例对象
 * sum:参数可以是复数，也可以是实数，返回两个或者多个复数（实数）之和，返回值是一个Complex实例对象。
 * sub:参数可以是复数，也可以是实数，返回两个复数（实数）只差，返回值是一个Complex实例对象。
 * mul:参数可以是复数，也可以是实数，返回两个或多个复数（实数）乘积，返回值是一个Complex实例对象。
 * div:参数可以是复数，也可以是实数，返回两个复数（实数）商，返回值是一个Complex实例对象。
 * con:参数必须是复数，返回复数的共轭复数。
 * abs:参数可以是复数，也可以是实数，返回复数（实数）的模，返回值是一个实数，Number类型。
 *
 * 工具方法：
 * is:判断一个对象是否是Complex实例对象,若是返回true，否则返回false
 */
const ComplexType={
    /**
     * 创建一个复数对象，返回值是complex实例对象类型
     * @param real 实部
     * @param imaginary 虚部
     * @param suffix 后缀i或者j
     * @returns {Complex}
     */
    set(real , imaginary, suffix){
        return new Complex(real , imaginary, suffix)
    },
    /**
     * @param complex
     * @returns {boolean}
     */
    is(complex){
        return complex.__proto__ === Complex.prototype
    },
    sum(){},
    sub(){},
    mul(){},
    div(){},
    con(){},
    abs(){}
}

/***************工具方法**************************/
/**
 * 判断一个参数是否是数值类型
 * @param value
 * @returns {boolean}
 */
function isNumber(value){
    return typeof value === 'number' && !isNaN(value)
}




//测试
let z

z =  ComplexType.set(0,0,'j')
console.log('0+0j:',z)
console.log('0+0j toString:',z.toString(),'\n') //0

z =  ComplexType.set(0,1,'j')
console.log('0+1*j:',z)
console.log('0+1*j toString:',z.toString(),'\n') //j

z =  ComplexType.set(0,2,'j')
console.log('0+2*j:',z)
console.log('0+2*j toString:',z.toString(),'\n') //2j

z =  ComplexType.set(0,-1,'j')
console.log('0-1*j:',z)
console.log('0-1*j toString:',z.toString(),'\n') //-j

z =  ComplexType.set(0,-2,'j')
console.log('0-2*j:',z)
console.log('0-2*j toString:',z.toString(),'\n') //-2j

/*****************************************************************/
z =  ComplexType.set(1,0,'j')
console.log('1+0*j:',z)
console.log('1+0*j toString:',z.toString(),'\n') //1

z = ComplexType.set(1,1,'j')
console.log('1+1*j:',z)
console.log('1+1*j toString:',z.toString(),'\n') //1+j

z =  ComplexType.set(1,2,'j')
console.log('1+2*j:',z)
console.log('1+2*j toString:',z.toString(),'\n') //1+2j

z =  ComplexType.set(1,-1,'j')
console.log('1-1*j:',z)
console.log('1-1*j toString:',z.toString(),'\n') //1-j

z =  ComplexType.set(1,-2,'j')
console.log('1-2*j:',z)
console.log('1-2*j toString:',z.toString(),'\n') //1-2j

z =  ComplexType.set(2,0,'j')
console.log('2+0*j:',z)
console.log('2+0*j toString:',z.toString(),'\n') //2

z =  ComplexType.set(2,1,'j')
console.log('2+1*j:',z)
console.log('2+1*j toString:',z.toString(),'\n') //2+j

z =  ComplexType.set(2,2,'j')
console.log('2+2*j:',z)
console.log('2+2*j toString:',z.toString(),'\n') //2+2j


z =  ComplexType.set(2,-1,'j')
console.log('2-2*j:',z)
console.log('2-2*j toString:',z.toString(),'\n') //2-j

z =  ComplexType.set(2,-2,'j')
console.log('2-2*j:',z)
console.log('2-2*j toString:',z.toString(),'\n') //2-2j

